#include <stdio.h>
#include <easyx.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#define SIZE 75
#define BoardSIZE 320

IMAGE background;
IMAGE img[12];
int map[4][4] =
{
	{0,0,0,0},
	{0,0,0,0},
	{0,0,0,0},
	{0,0,0,0}
};
typedef struct empty
{
	int x;
	int y;
}empty;
empty emptyArray[16];
int temp[4];
char user;
void Draw()
{
	for (int r = 0; r < 4; r++)
	{
		for (int c = 0; c < 4; c++)
		{
			switch (map[r][c])
			{
			case 0:
				putimage(4 + 79 * c, 4 + 79 * r, &img[0]);
				break;
			case 2:
				putimage(4 + 79 * c, 4 + 79 * r, &img[1]);
				break;
			case 4:
				putimage(4 + 79 * c, 4 + 79 * r, &img[2]);
				break;
			case 8:
				putimage(4 + 79 * c, 4 + 79 * r, &img[3]);
				break;
			case 16:
				putimage(4 + 79 * c, 4 + 79 * r, &img[4]);
				break;
			case 32:
				putimage(4 + 79 * c, 4 + 79 * r, &img[5]);
				break;
			case 64:
				putimage(4 + 79 * c, 4 + 79 * r, &img[6]);
				break;
			case 128:
				putimage(4 + 79 * c, 4 + 79 * r, &img[7]);
				break;
			case 256:
				putimage(4 + 79 * c, 4 + 79 * r, &img[8]);
				break;
			case 512:
				putimage(4 + 79 * c, 4 + 79 * r, &img[9]);
				break;
			case 1024:
				putimage(4 + 79 * c, 4 + 79 * r, &img[10]);
				break;
			case 2048:
				putimage(4 + 79 * c, 4 + 79 * r, &img[11]);
				break;
			default:
				break;
			}
		}
	}
}
void LoadGame()
{
	loadimage(&background, "./images/background.png", 320, 320, true);
	loadimage(&img[0], "./images/0.png", 75, 75, true);
	loadimage(&img[1], "./images/2.png", 75, 75, true);
	loadimage(&img[2], "./images/4.png", 75, 75, true);
	loadimage(&img[3], "./images/8.png", 75, 75, true);
	loadimage(&img[4], "./images/16.png", 75, 75, true);
	loadimage(&img[5], "./images/32.png", 75, 75, true);
	loadimage(&img[6], "./images/64.png", 75, 75, true);
	loadimage(&img[7], "./images/128.png", 75, 75, true);
	loadimage(&img[8], "./images/256.png", 75, 75, true);
	loadimage(&img[9], "./images/512.png", 75, 75, true);
	loadimage(&img[10], "./images/1024.png", 75, 75, true);
	loadimage(&img[11], "./images/2048.png", 75, 75, true);
	putimage(0, 0, &background);
}
void RemoveZero(int* onearr)
{
	for (int i=0;i<4;i++)
		temp[i] = 0;
	int j = 0;
	for (int i = 0; i < 4;i++)
	{
		if (onearr[i]!=0)
		{
			temp[j] = onearr[i];
			j++;
		}
	}
}
void Merge(int *onearr)
{
	RemoveZero(onearr);
	for (int i=0;i<3;i++)
	{
		if (temp[i]==temp[i+1])
		{
			temp[i] = temp[i] * 2;
			temp[i + 1] = 0;
		}
	}
}
int Empty()
{
	int j = 0;
	for (int r = 0;r < 4;r++)
	{
		for (int c = 0;c < 4;c++)
		{
			if (map[r][c] == 0)
			{
				emptyArray[j].x = r;
				emptyArray[j].y = c;
				j++;
			}
		}
	}
	return j;
}
int RandomNumber()
{
	srand((unsigned int)time(NULL));
	return rand() % Empty();
}
void CreatNumber()
{
	int num = RandomNumber();
	map[emptyArray[num].x][emptyArray[num].y] = 2;
}
void MoveLeft()
{
	int onearray[4] = {0,0,0,0};
	for (int r=0;r<4;r++)
	{
		for (int c=0;c<4;c++)
		{
			onearray[c] = map[r][c];
			Merge(onearray);
		}
		for (int c = 0;c < 4;c++)
			map[r][c] = temp[c];
	}
}
void MoveRight()
{
	int onearray[4] = {0,0,0,0};
	for (int r = 0;r < 4;r++)
	{
		for (int c = 0;c < 4;c++)
		{
			onearray[c] = map[r][3-c];
			Merge(onearray);
		}
		for (int c = 0;c < 4;c++)
			map[r][3-c] = temp[c];
	}
}
void MoveUp()
{
	int onearray[4] = {0,0,0,0};
	for (int c = 0;c < 4;c++)
	{
		for (int r = 0;r < 4;r++)
		{
			onearray[r] = map[r][c];
			Merge(onearray);
		}
		for (int r = 0;r < 4;r++)
			map[r][c] = temp[r];
	}
}
void MoveDown()
{
	int onearray[4] = {0,0,0,0};
	for (int c = 0;c < 4;c++)
	{
		for (int r = 0;r < 4;r++)
		{
			onearray[r] = map[3-r][c];
			Merge(onearray);
		}
		for (int r = 0;r < 4;r++)
			map[3-r][c] = temp[r];
	}
}
void Move()
{
	user = _getch();
	switch (user)
	{
		case 'a':
			MoveLeft();
			CreatNumber();
			CreatNumber();
			Draw();
			break;
		case 'd':
			MoveRight();
			CreatNumber();
			CreatNumber();
			Draw();
			break;
		case 'w':
			MoveUp();
			CreatNumber();
			CreatNumber();
			Draw();
			break;
		case 's':
			MoveDown();
			CreatNumber();
			CreatNumber();
			Draw();
			break;
		default:
			break;
	}
}
void IsLoss()
{
	if (Empty()==0)
	{
		closegraph();
	}
}
int main()
{
	initgraph(320, 320);
	LoadGame();
	CreatNumber();
	CreatNumber();
	Draw();
	while (1)
	{
		Move();
		IsLoss();
	}
	return 0;
}